package com.mfl.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.mfl.common.PageResult;
import com.mfl.constant.IdentityConstant;
import com.mfl.constant.MessageConstant;
import com.mfl.context.BaseContext;
import com.mfl.exception.*;
import com.mfl.mapper.PostMapper;
import com.mfl.mapper.PostRemarkMapper;
import com.mfl.mapper.UserMapper;
import com.mfl.pojo.dto.UserDTO;
import com.mfl.pojo.dto.UserLoginDTO;
import com.mfl.pojo.dto.UserPageQueryDTO;
import com.mfl.pojo.entity.User;
import com.mfl.pojo.vo.UserPageQueryVO;
import com.mfl.pojo.vo.UserVO;
import com.mfl.properties.AESProperties;
import com.mfl.service.UserService;
import com.mfl.utils.AESUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.nio.file.attribute.UserPrincipalNotFoundException;
import java.time.LocalDateTime;
import java.util.List;

@Slf4j
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private AESProperties aesProperties;
    @Autowired
    private PostMapper postMapper;
    @Autowired
    private PostRemarkMapper postRemarkMapper;

    /**
     * 新增用户
     *
     * @param userDTO
     */
    @Override
    public void insert(UserDTO userDTO) {
        // 判断用户是否存在
        User u = userMapper.getByUserName(userDTO.getUserName());
        if (u != null) {
            throw new AccountAlreadyExistsException(MessageConstant.ACCOUNT_ALREADY_EXISTS);
        }
        // 密码加密
        String password = null;
        try {
            password = AESUtil.encrypt(userDTO.getUserPwd(), aesProperties.getSecretKey());
        } catch (Exception e) {
            throw new ServerErrorException(MessageConstant.SERVER_ERROR);
        }
        User user = User.builder()
                .userName(userDTO.getUserName())
                .userPwd(password)
                .name(userDTO.getName())
                .gender(userDTO.getGender())
                .phone(userDTO.getPhone())
                .status(userDTO.getIdentity() == IdentityConstant.ORDINARY_USER ? 1 : userDTO.getStatus())
                .avatar(userDTO.getAvatar())
                .createUser(userDTO.getIdentity() == IdentityConstant.ORDINARY_USER ? -1 : BaseContext.getCurrentId())
                .createTime(LocalDateTime.now())
                .build();
        userMapper.insert(user);
    }

    /**
     * 分页查询用户信息
     *
     * @param userPageQueryDTO
     * @return
     */
    @Override
    public PageResult pageQuery(UserPageQueryDTO userPageQueryDTO) {
        PageHelper.startPage(userPageQueryDTO.getPage(), userPageQueryDTO.getPageSize());
        Page<UserPageQueryVO> page = userMapper.pageQuery(userPageQueryDTO);
        page.getResult().forEach(item -> {
            try {
                String password = AESUtil.decrypt(item.getUserPwd(), aesProperties.getSecretKey());
                item.setUserPwd(password);
            } catch (Exception e) {
                throw new ServerErrorException(MessageConstant.SERVER_ERROR);
            }
        });
        return new PageResult(page.getTotal(), page.getResult());
    }

    /**
     * 修改用户状态
     *
     * @param status
     * @param id
     */
    @Override
    public void updateStatus(Integer status, Integer id) {
        userMapper.updateStatus(status, id);
    }

    /**
     * 批量删除用户
     *
     * @param ids
     */
    @Transactional
    @Override
    public void batchDelete(List<Integer> ids) {
        userMapper.deleteByIds(ids);
        // 删除用户之后，需要将用户关联的帖子删除
        // 先查到对应帖子的id后删除帖子的回复
        List<Integer> list = postMapper.getIdByCreateUser(ids);
        if(list.size() > 0){
            // 删除帖子回复
            postRemarkMapper.deleteByPostIds(list);
            // 删除帖子
            postMapper.deleteByUserIds(ids);
        }
    }

    /**
     * 根据id查询用户信息
     *
     * @param id
     * @return
     */
    @Override
    public UserVO getUserById(int id) {
        User user = userMapper.getById(id);
        String password = null;
        try {
            password = AESUtil.decrypt(user.getUserPwd(), aesProperties.getSecretKey());
        } catch (Exception e) {
            throw new ServerErrorException(MessageConstant.SERVER_ERROR);
        }
        return UserVO.builder()
                .id(user.getId())
                .userName(user.getUserName())
                .userPwd(password)
                .name(user.getName())
                .gender(user.getGender())
                .phone(user.getPhone())
                .avatar(user.getAvatar())
                .introduce(user.getIntroduce())
                .visitor(user.getVisitor())
                .status(user.getStatus())
                .createTime(user.getCreateTime())
                .build();
    }

    /**
     * 修改用户信息
     *
     * @param userDTO
     */
    @Override
    public void update(UserDTO userDTO) {
        String password = null;
        try {
            password = AESUtil.encrypt(userDTO.getUserPwd(), aesProperties.getSecretKey());
        } catch (Exception e) {
            throw new ServerErrorException(MessageConstant.SERVER_ERROR);
        }
        User user = User.builder()
                .id(userDTO.getId())
                .userName(userDTO.getUserName())
                .userPwd(password)
                .name(userDTO.getName())
                .gender(userDTO.getGender())
                .phone(userDTO.getPhone())
                .avatar(userDTO.getAvatar())
                .introduce(userDTO.getIntroduce())
                .status(userDTO.getStatus())
                .visitor(userDTO.getVisitor())
                .updateUser(BaseContext.getCurrentId())
                .updateTime(LocalDateTime.now())
                .build();
        userMapper.update(user);
    }

    /**
     * 用户登录
     *
     * @param userLoginDTO
     * @return
     */
    @Override
    public User login(UserLoginDTO userLoginDTO) {
        String username = userLoginDTO.getUserName();
        String password = userLoginDTO.getUserPwd();

        // 判断用户是否存在
        User user = userMapper.getByUserName(username);
        if (user == null) {
            throw new AccountNotFoundException(MessageConstant.ACCOUNT_NOT_FOUND);
        }

        // 查看账号状态
        if (user.getStatus() == 0) {
            throw new AccountNotAvailable(MessageConstant.ACCOUNT_NOT_AVAILABLE);
        }

        // 密码加密，进行密码判断
        try {
            password = AESUtil.encrypt(password, aesProperties.getSecretKey());
            if (!password.equals(user.getUserPwd())) {
                throw new PasswordErrorException(MessageConstant.PASSWORD_ERROR);
            }
        } catch (Exception e) {
            throw new PasswordErrorException(MessageConstant.PASSWORD_ERROR);
        }

        return user;
    }

    /**
     * 修改用户信息（用户端，不包含密码）
     * @param userDTO
     */
    @Override
    public void updateUserInfo(UserDTO userDTO) {
        User user = User.builder()
                .id(userDTO.getId())
                .userName(userDTO.getUserName())
                .name(userDTO.getName())
                .gender(userDTO.getGender())
                .phone(userDTO.getPhone())
                .avatar(userDTO.getAvatar())
                .introduce(userDTO.getIntroduce())
                .visitor(userDTO.getVisitor())
                .status(userDTO.getStatus())
                .updateUser(BaseContext.getCurrentId())
                .updateTime(LocalDateTime.now())
                .build();
        System.out.println(user);
        userMapper.update(user);
    }

    /**
     * 检查密码
     * @param userDTO
     * @return
     */
    @Override
    public Boolean checkPwd(UserDTO userDTO) {
        String password = null;
        try {
            password = AESUtil.encrypt(userDTO.getUserPwd(), aesProperties.getSecretKey());
        } catch (Exception e) {
            throw new ServerErrorException(MessageConstant.SERVER_ERROR);
        }
        User user = User.builder()
                .id(userDTO.getId())
                .userPwd(password)
                .build();
        return userMapper.checkPwd(user);
    }

    /**
     * 修改密码
     * @param userDTO
     */
    @Override
    public void updatePwd(UserDTO userDTO) {
        String password = null;
        try {
            password = AESUtil.encrypt(userDTO.getUserPwd(), aesProperties.getSecretKey());
        } catch (Exception e) {
            throw new ServerErrorException(MessageConstant.SERVER_ERROR);
        }
        User user = User.builder()
                .id(userDTO.getId())
                .userPwd(password)
                .build();
        userMapper.updatePwd(user);
    }
}
